package com.itheima.shiro;

import com.itheima.domain.User;
import com.itheima.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by Chilly Cui on 2020/9/10.
 */
public class SecondRealm extends AuthorizingRealm {

    @Autowired
    private UserService userSerivce;

    /**
     * 设置密码匹配
     */
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //加密方式
        hashedCredentialsMatcher.setHashAlgorithmName("SHA1");
        //加密次数
        hashedCredentialsMatcher.setHashIterations(1024);
        //存储散列后的密码是否为16进制
        //hashedCredentialsMatcher.isStoredCredentialsHexEncoded();
        super.setCredentialsMatcher(hashedCredentialsMatcher);
    }

    /**
     * 执行授权逻辑
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行授权逻辑");

        //1、从 PrincipalCollection 中获取登录用户的信息
        //2、利用登录用户的信息获取用户的角色
        //3、创建 SimpleAuthorizationInfo 并设置属性roles
        //4、返回 SimpleAuthorizationInfo对象

        User principal = (User) principals.getPrimaryPrincipal();
        Set<String> roles = new HashSet<>();
        roles.add("user");
        if ("admin".equals(principal.getName())) {
            roles.add("admin");
        }

        //给资源进行授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);

        //添加资源的授权字符串
        //info.addStringPermission("user:add");

        //到数据库查询当前登录用户的授权字符串
        //获取当前登录用户
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        User dbUser = userSerivce.findById(user.getId());

        info.addStringPermission(dbUser.getPerms());

        return info;
    }

    /**
     * 执行认证逻辑
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
        System.out.println("执行认证逻辑 SecondRealm");
        System.out.println("执行认证逻辑 SecondRealm getName()" + getName());

        //编写shiro判断逻辑，判断用户名和密码
        //1.判断用户名
        UsernamePasswordToken token = (UsernamePasswordToken) arg0;

        String username = token.getUsername();
        User user = userSerivce.findByNameBySHA1(username);

        if (user == null) {
            //用户名不存在
            throw new UnknownAccountException("用户不存在");
            //return null;//shiro底层会抛出 UnKnowAccountException
        }

        //根据用户信息，决定是否抛出其他的异常，比如账号被锁定
        if ("monster".equals(user.getName())) {
            throw new LockedAccountException("用户被锁定");
        }

        /*Object credentials = null; //加盐加密之后的密码
        if ("admin".equals(user.getName())){
            credentials = "ce2f6417c7e1d32c1d81a797ee0b499f87c5de06";
        }else if ("user".equals(user.getName())){
            credentials="073d4c3ae812935f23cb3f2a71943f49e082a718";
        }*/

        Object credentials = user.getPassword(); //加盐加密之后的密码
        ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt()); //盐值

        //2.判断密码
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, credentials, credentialsSalt, getName());
        return authenticationInfo;
    }


    public static void main(String[] args) {
        //以下是对不同的用户进行加盐加密，盐值为用户名
        String hashAlgorithmName = "SHA1"; //加密算法
        Object credentials = "123456"; //密码
//        ByteSource salt = ByteSource.Util.bytes("admin");//ce2f6417c7e1d32c1d81a797ee0b499f87c5de06
//        ByteSource salt = ByteSource.Util.bytes("user");//073d4c3ae812935f23cb3f2a71943f49e082a718
        ByteSource salt = ByteSource.Util.bytes("monster");//d2f1601db6a6530d970afb4172a7141bedbf3d11
        int hashIterations = 1024;

        SimpleHash simpleHash = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
        System.out.println(simpleHash.toString());
    }

}
